﻿#region Librerias

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESF.General;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;

#endregion


namespace ESF.FileProcessing
{
	public class RenameHelper : BaseTaskManager
	{
		#region Miembros

		private bool _RenameBySecuence;
		private string _Prefix;
		private string _Sufix;
		private string _Extension;
		private string _Remove;

		#endregion


		#region Constructor

		public RenameHelper (ProcessHelper.ReportProgressDelegate pdelReportProgressDelegate = null)
			: base (pdelReportProgressDelegate) {}

		#endregion


		#region Funciones

		public static string ReNameFilenameRegex (string pFileName, string pRegExRename, string pReplace)
		{
			return new Regex(pRegExRename).Replace(Path.GetFileNameWithoutExtension (pFileName), pReplace) + Path.GetExtension (pFileName);
		}


		public void Initialize (bool pRenameBySecuence, string pPrefix, string pSufix, string pExtension, string pRemove, string pLogFileName)
		{
			_RenameBySecuence = pRenameBySecuence;
			_Prefix = pPrefix;
			_Sufix = pSufix;
			_Extension = pExtension;
			_Remove = pRemove;
			
			InitializeLog (pLogFileName);
		}

		
		public void RenameInDirectories (string pDirectoryPath, params string[] pExtensions)
		{
			try
			{
				Start (ESF.General.FileHelper.GetDirectoryCount (pDirectoryPath));

				FileHelper.ExecuteInDirectory (pDirectoryPath, RenameInDirectory, pExtensions);
			}
			catch (OperationCanceledException cex)
			{
				Log.Error(cex);
			}
			finally
			{
				Stop();
			}
		}


		public void RenameInDirectory(string pDirectoryPath, string[] pExtensions)
		{
			IncrementReadyCount ();

			try
			{
				#region Por Secuencia
			
				if (_RenameBySecuence)
				{
					string firstName;

					string firstExtension;

					StringBuilder jumpMessage = new StringBuilder ();

					long index;
					long? tempIndex;

					string padFirst;

					bool continueLogging = true;


					// Nombre (solo) del primer archivo encontrado
					firstName = (from FL in Directory.EnumerateFiles(pDirectoryPath) 
						where TextHelper.IsIn(Path.GetExtension(FL), pExtensions) select Path.GetFileName(FL)).FirstOrDefault();

					firstExtension = Path.GetExtension(firstName);
					firstName = Path.GetFileNameWithoutExtension(firstName);

					if (string.IsNullOrWhiteSpace(firstName)) { return; }

					if (firstName.Length > 18) { throw new GenericInfoException ("La longitud del nombre no puede ser asignada como numeros desde 1 pues su longitud supera la soportada: 18, con: " + firstName); }

					padFirst = new String('0', firstName.Length);


					index = 1;

					jumpMessage.AppendFormat ("Analizando por saltos el directorio:\n{0}", pDirectoryPath);
					jumpMessage.AppendLine ();


					// Renombrar todos los archivos del directorio con un sufijo
					foreach (string pFileName in ESF.General.FileHelper.ListFiles (pDirectoryPath, pFileExtensions: pExtensions, pSearchOption: SearchOption.TopDirectoryOnly).OrderBy (s => s))
					{
						string expectedName = string.Format("{0}{1}", index.ToString(padFirst), firstExtension);

						if (String.Compare (Path.GetFileName (pFileName), expectedName, true) != 0)
						{
							if (continueLogging)
							{
								jumpMessage.AppendFormat ("El archivo {0} se esperaba tuviese un nombre como {1}", pFileName, expectedName);
								jumpMessage.AppendLine ();
							}

							tempIndex = TextHelper.GetNullableLong (Path.GetFileNameWithoutExtension (pFileName));

							if (tempIndex != null)
							{
								index = tempIndex.Value;
							}
							else
							{
								continueLogging = false;
							}

							index ++;
						}

						string newName = Path.Combine(
								pDirectoryPath,
								string.Format("{0}{1}{2}", Path.GetFileName(pFileName), Guid.NewGuid().ToString(), Path.GetExtension(pFileName)));

						File.Move(pFileName, newName);

						index ++;
					}


					index = 1;

					foreach (string pFileName in ESF.General.FileHelper.ListFiles (pDirectoryPath, pFileExtensions: pExtensions, pSearchOption: SearchOption.TopDirectoryOnly).OrderBy (s => s))
					{
						string newName = Path.Combine(Path.GetDirectoryName(pFileName), string.Format("{0}{1}", index.ToString(padFirst), firstExtension));
						
						File.Move(pFileName, newName);

						index++;
					}

					LogWriter.Write (jumpMessage.ToString ());
				}

				#endregion

				#region Por Prefijos

				if (!string.IsNullOrEmpty (_Prefix) || !string.IsNullOrEmpty (_Sufix) || !string.IsNullOrEmpty (_Remove))
				{
					foreach (string pFilePath in ESF.General.FileHelper.ListFiles (pDirectoryPath, pFileExtensions: pExtensions, pSearchOption: SearchOption.TopDirectoryOnly).Where(f => TextHelper.IsIn(Path.GetExtension(f), pExtensions)).OrderBy (s => s))
					{
						string newName;


						_Extension = _Extension.Trim();

						newName = Path.GetFileNameWithoutExtension(pFilePath);

						if (!TextHelper.IsEmpty(_Remove))
						{
							newName = newName.Replace(_Remove, string.Empty);
						}

						newName = _Prefix + newName + _Sufix;

						if (!TextHelper.IsEmpty(_Extension)
							&& Path.GetExtension(pFilePath).ToUpper() != _Extension.ToUpper())
						{
							newName += _Extension;
						}
						else
						{
							newName += Path.GetExtension(pFilePath);
						}

						File.Move(pFilePath, Path.Combine(Path.GetDirectoryName(pFilePath), newName));
					}
				}

				#endregion
			}
			catch (Exception pEx)
			{
				pEx.Data.Add("Directory", pDirectoryPath);

				Log.Error(pEx); 
				
				IncrementErrorCount(pEx);
			}
			finally
			{
				ReportProgress ();
			}
		}

		#endregion
	}
}
